package com.echo.code.thread.atomic;

import java.lang.reflect.Field;
import java.util.Objects;
import sun.misc.Unsafe;

/**
 * UnSafeExam Created by baiyap on 2018/10/10.
 */
public class UnSafeExam {

  public static void main(String[] args) throws InstantiationException, NoSuchFieldException {
    // 获得一个UnSafe实例
    Unsafe unsafe = null;
    try {
      Field f = Unsafe.class.getDeclaredField("theUnsafe");
      f.setAccessible(true);
      unsafe = (Unsafe) f.get(null);
    } catch (NoSuchFieldException e) {
      e.printStackTrace();
    } catch (IllegalAccessException e) {
      e.printStackTrace();
    }

    if (Objects.nonNull(unsafe)) {
      try {
        // 构造一个对象，且不调用其构造函数
        Test test = (Test) unsafe.allocateInstance(Test.class);
        // 得到一个对象内部属性的地址
        long x_address = unsafe.objectFieldOffset(Test.class.getDeclaredField("x"));
        // 直接给此属性赋值
        unsafe.getAndSetInt(test, x_address, 47);
        System.out.println(test.getX());
      } catch (InstantiationException e) {
        e.printStackTrace();
      } catch (NoSuchFieldException e) {
        e.printStackTrace();
      }
    }

    // CAS
    if (Objects.nonNull(unsafe)) {
      Test test = (Test) unsafe.allocateInstance(Test.class);
      long x_address = unsafe.objectFieldOffset(Test.class.getDeclaredField("x"));
      unsafe.getAndSetInt(test, x_address, 47);
      unsafe.compareAndSwapInt(test, x_address, 47, 78);
      System.out.println("After CAS:" + test.getX());
    }

  }

  public static class Test {

    private int x;

    public Test(int x) {
      this.x = x;
      System.out.println("Test constructor");
    }

    public int getX() {
      return x;
    }
  }
}
